module(...,package.seeall)

require"split"
require"record"

local msgQuene = {}

function procMsg(mqttc)
	while #msgQuene>0 do
		local outMsg = table.remove(msgQuene,1)
		local result = mqttc:publish(outMsg.t,outMsg.p,outMsg.q)
		if outMsg.user then outMsg.user.cb(result,outMsg.user.para) end
		if not result then return end
	end
	return true
end

function insertOutMsg(topic,payload,qos,user)
	table.insert(msgQuene,{t=topic,p=payload,q=0,user=user})
end

function waitForSend()
	return #msgQuene > 0
end

local tGet = {
	["VERSION"] = function() return _G.VERSION end,
	PROJECTID = function() return _G.PRJID end,
	PROJECT = function() return _G.PROJECT end,
	HEART = function() return nvm.get("heart") end,
	IMEI = misc.getimei,
	IMSI = sim.getimsi,
	ICCID = sim.geticcid,
	RSSI = net.getRssi,
	CELLINFOEXT = net.getCellInfoExt,
	TA = net.getTa,
	STATUS = function() return {
		charger=battery.getCharger() and 1 or 0,
		volt=battery.getVoltage(),
		chgState=battery.getChargingState(),
	} end,
	PARAVER = function() return nvm.get("paraver") end,
}
local function getf(id)
	assert(tGet[id] ~= nil,"getf nil id:" .. id)
	return tGet[id]()
end

function enTopic(t)
	return "/v1/device/"..tGet["IMEI"]().."/"..t
end

function enTopic2(src,dst,t)
	return "/v1/chat/".._G.PRJID.."/"..src.."/"..dst.."/"..t
end

local function heartReport()
	insertOutMsg(enTopic("devdata"),protoair.pack(protoair.HEART),0)
	sys.timer_start(heartReport,nvm.get("heart")*1000)
end

function locReport(typ,user)
	insertOutMsg(enTopic("devdata"),protoair.pack(typ and protoair.GPSLBSWIFIEXT or protoair.LBS3,typ),0,user)
	sys.timer_start(heartReport,nvm.get("heart")*1000)
	sys.timer_start(locReport,nvm.get("rptfreq")*1000)
end

function init()
	insertOutMsg(enTopic("devdata"),protoair.pack(protoair.INFO),0)
	locReport()
end



local devpararpting

function getdevpara(idx)
	devpararpting = true
	local s = split.getfdata(nvm.paraname,idx,2048)
	log.info("linkout.getdevpara",idx,string.len(s))
	if not s or s=="" then
		devpararpting = false
	end
	return s
end

local function devpararptreq(result,idx)
	log.info("linkout.devpararptreq",devpararpting,idx)
	if not devpararpting or idx then
		local s = getdevpara(idx or 1)
		if s and s~="" then insertOutMsg(enTopic("devpararpt"),protoair.pack(protoair.RPTPARA,pack.pack("bA",protoair.LOG,s)),1,{cb=devpararptreq,para=(idx or 1)+1}) end
	end
end

local chatSeq,sndingChat = 0
local RCD_READ_UNIT = 1024

local function sndchatrcdcnf(result,status)
	sys.publish("SND_NEW_CHAT_CNF",result)
	sndingChat = status
end

local function sndchatrcdnxt(result,para)
	if not result then log.warn("linkout.sndchatrcdnxt send error") sndchatrcdcnf(false) return end
	local topic,rcdCnt,rcdIdx,rcdDur = string.match(para,"(.-)!(.-)!(.-)!(.+)")
	log.info("linkout.sndchatrcdnxt",para,topic,rcdCnt,rcdIdx,rcdDur)
	if not rcdDur then log.warn("linkout.sndchatrcdnxt para error") sndchatrcdcnf(false) return end
	if tonumber(rcdCnt)==tonumber(rcdIdx) then sndchatrcdcnf(true) return end
	insertOutMsg(topic,
		protoair.pack(protoair.CHATRCD,tonumber(chatSeq),tonumber(rcdCnt),tonumber(rcdIdx)+1,0,tonumber(rcdDur),record.getdata(tonumber(rcdIdx)*RCD_READ_UNIT,RCD_READ_UNIT)),
		0,
		{cb=sndchatrcdnxt,para=topic.."!"..rcdCnt.."!"..(tonumber(rcdIdx)+1).."!"..rcdDur})
end
--dstid：联系人号码或者群组id
local function sndchatrcdreq(dstid,single)
	if sndingChat then log.warn("linkout.sndchatrcdreq snding") sndchatrcdcnf(false,true) return end
	if not linkair.isReady() then log.warn('linkout.sndchatrcdreq', 'linkair not ready') sndchatrcdcnf(false) return end

	local rcdSize,rcdDur = record.getsize()
	if rcdSize==0 or rcdDur==0 then log.warn("linkout.sndchatrcdreq size error",rcdSize,rcdDur) sndchatrcdcnf(false) return end
	local rcdCnt = (rcdSize-1)/RCD_READ_UNIT+1
	chatSeq = (chatSeq+1)>0 and (chatSeq+1) or 0
	sndingChat = true

	local topic = enTopic2(misc.getimei(),dstid,((single or single==nil) and "single" or "group").."/dtos")
	insertOutMsg(topic,protoair.pack(protoair.CHATRCD,chatSeq,rcdCnt,1,0,rcdDur,record.getdata(0,RCD_READ_UNIT)),0,{cb=sndchatrcdnxt,para=topic.."!"..rcdCnt.."!1!"..rcdDur})
end

local imgSeq,sndingImg = 0
local IMG_READ_UNIT = 2048

local function sndImgCnf(result,status)
	sys.publish("SND_IMG_CNF",result)
	sndingImg = status
end

local function sndImgNxt(result,para)
	if not result then log.warn("linkout.sndImgNxt send error") sndImgCnf(false) return end
	local topic,cmdTyp,imgCnt,imgIdx,imgPath = string.match(para,"(.-)!(.-)!(.-)!(.-)!(.+)")
	log.info("linkout.sndImgNxt",para,topic,imgCnt,imgIdx)
	if not imgIdx then log.warn("linkout.sndImgNxt para error") sndImgCnf(false) return end
	if tonumber(imgCnt)==tonumber(imgIdx) then sndImgCnf(true) return end
	insertOutMsg(topic,
		protoair.pack(protoair.IMG_RPT,tonumber(cmdTyp),tonumber(imgSeq),tonumber(imgCnt),tonumber(imgIdx)+1,0,split.getfdata(imgPath,tonumber(imgIdx)+1,IMG_READ_UNIT)),
		0,
		{cb=sndImgNxt,para=topic.."!"..cmdTyp.."!"..imgCnt.."!"..(tonumber(imgIdx)+1).."!"..imgPath})
end
--path：照片路径
--cmdTyp：0表示远程拍摄上报，1表示设备主动上报
local function sndImgReq(path,cmdTyp)
	if sndingImg then log.warn("linkout.sndImgReq snding") sndImgCnf(false,true) return end
	if not linkair.isReady() then log.warn('linkout.sndImgReq', 'linkair not ready') sndImgCnf(false) return end

	local imgCnt = split.getfinf(path,IMG_READ_UNIT)
	if imgCnt==0 then log.warn("linkout.sndImgReq size error") sndImgCnf(false) return end
	imgSeq = (imgSeq+1)>0 and (imgSeq+1) or 0
	sndingImg = true

	local topic = "/v1/".._G.PRJID.."/"..tGet["IMEI"]().."/img"
	insertOutMsg(topic,protoair.pack(protoair.IMG_RPT,cmdTyp,imgSeq,imgCnt,1,0,split.getfdata(path,1,IMG_READ_UNIT)),0,{cb=sndImgNxt,para=topic.."!"..cmdTyp.."!"..imgCnt.."!1!"..path})
end

local function sosRptCnf(result)
	sys.publish("SOS_RPT_CNF",result)
end

local function sosRptReq()
	if not linkair.isReady() then log.warn('linkout.sosRptReq', 'linkair not ready') sosRptCnf(false) return end
	locReport(protoair.SOSPOS,{cb=sosRptCnf})
end

function unInit()
	sys.timer_stop(locReport)
	sys.timer_stop(heartReport)
	while #msgQuene>0 do
		local outMsg = table.remove(msgQuene,1)
		if outMsg.user then outMsg.user.cb(false,outMsg.user.para) end
	end
	devpararpting = nil
end

sys.subscribe("DEVPARA_RPT_REQ",devpararptreq)
sys.subscribe("SND_NEW_CHAT_REQ",sndchatrcdreq)
sys.subscribe("SND_IMG_REQ",sndImgReq)
sys.subscribe("SOS_RPT_REQ",sosRptReq)
protoair.reget(getf)
